<template>
  <div class="questions-block relative left-15px bottom-300px">
    <ul class="questions-block-body py-10px" @touchstart="touchStart" @touchend="touchend">
      <li v-for="item in questionsList" :key="item.id" class="mb-10px" @click="$emit('itemClick', item.question_title)">
        <qu-wrapper>
          {{ item.question_title }}
        </qu-wrapper>
      </li>
    </ul>
  </div>
</template>

<script
  lang="ts"
  name="QuestionBlock"
  setup
>
import { useTtsaStore } from '@/store/ttsa'

defineEmits(['itemClick'])

// 非响应式变量
let scrollTop = 0
const stepTotal = 8 // 执行完单次问题列表移动动画的帧数，这会影响动画时长。
let timer = null // 问题列表动画定时器
const duration = 3500 // 问题滚动间隔

// stores
const ttsaStore = useTtsaStore()

// computeds
const questionsList = computed(() => ttsaStore.questions)

// 执行问题列表移动动画
const runTime = (end: number, ele: Element, step?: number) => {
  // 按照屏幕刷新率为 60HZ 计算。目前大部分手机刷新率为60，有些厂商吹牛到90，实际差别不大，按照60计算不影响动画流畅程度。
  // 目标为 150 ms 完成移动动画。
  // 150ms / (1000/60) 约等于9帧。 即9帧完成动画。减少帧数会降低动画总体执行时间，反之亦然。
  // 目标位置-初始位置 / 9 为每帧要移动的距离。 (end-start)/9

  // 每一步动画开始执行时，读取当前scrollTop
  let start = scrollTop
  if (!step) {
    step = 1
  }
  // 目标位置 - 初始位置，除以总步数 = 每一步的步长
  const stepSize = (end - start) / stepTotal
  window.requestAnimationFrame(() => {
    // 初始位置+步数*步长 = 当前scrollTop 的位置
    ele.scrollTop = start + stepSize * step
    if (step <= stepTotal) {
      runTime(end, ele, ++step)
    } else {
      scrollTop = ele.scrollTop = end
    }
  })
}
// 初始化问题列表动画
const initAnimation = () => {
  const root = document.querySelector('.questions-block-body')
  const list = document.querySelectorAll('.questions-block-body>li')
  // 获取计算单个li内容高度
  const eleHeight = list[0].getBoundingClientRect().height
  const liMargin = Number(getComputedStyle(list[0]).marginBottom.slice(0, -2) || 0)
  const boxHeight = eleHeight + liMargin
  const contHeight = list.length * boxHeight
  let i = 0
  // 如果当前滚动到某个位置了，则动画从当前位置开始执行
  if (root.scrollTop) {
    i = root.scrollTop / boxHeight | 0 || 0
    scrollTop = root.scrollTop
  }
  // 启动一个每隔 duration 执行一次的定时器，动画主引擎
  timer = setInterval(() => {
    let scrollValue = (eleHeight + liMargin) * ++i
    // 滚动到底之后重置
    if (scrollValue > contHeight - root.clientHeight) {
      scrollValue = 0
      i = 0
    }
    // 用于执行动画的方法
    runTime(scrollValue, root)
  }, duration)
}
// 清除问题列表动画
const clearAnimation = () => {
  clearInterval(timer)
}
// 用户滑动问题列表时取消动画
const touchStart = () => {
  clearAnimation()
}
// 用户滑动问题列表结束时初始化动画
const touchend = () => {
  initAnimation()
}

onMounted(() => {
  initAnimation()
})

onBeforeUnmount(() => {
  clearAnimation()
})

</script>

<style
  lang="scss"
  scoped
>
.questions-block {
  @apply overflow-hidden;


  &,
  .questions-block-body {
    max-width: 247px;
    max-height: 158px;
    background: transparent;
    mask: linear-gradient(transparent 0, black 20px, black 135px, transparent 100%);
    -webkit-mask: linear-gradient(transparent 0, black 20px, black 135px, transparent 100%);
  }

  .questions-block-body {
    @apply overflow-x-hidden overflow-y-scroll whitespace-nowrap z-0;
    scrollbar-width: none;

    &::-webkit-scrollbar {
      display: none;
    }

  }
}
</style>
